{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Providing Data\n",
    "No data visualization is possible without the underlying data to be represented. In this section, the various ways of providing data for plots is explained, from passing data values directly to creating a `ColumnDataSource` and filtering using a `CDSView`.\n",
    "\n",
    "没有底层数据的表示，就不可能有数据可视化。 在本节中，将解释为绘图提供数据的各种方式，从直接传递数据值到创建`ColumnDataSource`和使用 `CDSView`进行筛选。\n",
    "\n",
    "# 2. Providing data directly\n",
    "In Bokeh, it is possible to pass lists of values directly into plotting functions. In the example below, the data, x_values and y_values, are passed directly to the circle plotting method (see Plotting with Basic Glyphs for more examples).\n",
    "\n",
    "在 Bokeh，可以将值列表直接传递给绘图函数。 在下面的示例中，data、x_values和y_values直接传递给圆形绘图方法(更多示例请参见使用基本标志符号绘图)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"display: table;\"><div style=\"display: table-row;\"><div style=\"display: table-cell;\"><b title=\"bokeh.models.renderers.GlyphRenderer\">GlyphRenderer</b>(</div><div style=\"display: table-cell;\">id&nbsp;=&nbsp;'1036', <span id=\"1039\" style=\"cursor: pointer;\">&hellip;)</span></div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">data_source&nbsp;=&nbsp;ColumnDataSource(id='1033', ...),</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">glyph&nbsp;=&nbsp;Circle(id='1034', ...),</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">hover_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_event_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_property_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">level&nbsp;=&nbsp;'glyph',</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted&nbsp;=&nbsp;False,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">name&nbsp;=&nbsp;None,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">nonselection_glyph&nbsp;=&nbsp;Circle(id='1035', ...),</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">selection_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">subscribed_events&nbsp;=&nbsp;[],</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags&nbsp;=&nbsp;[],</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">view&nbsp;=&nbsp;CDSView(id='1037', ...),</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">visible&nbsp;=&nbsp;True,</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_range_name&nbsp;=&nbsp;'default',</div></div><div class=\"1038\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_range_name&nbsp;=&nbsp;'default')</div></div></div>\n",
       "<script>\n",
       "(function() {\n",
       "  var expanded = false;\n",
       "  var ellipsis = document.getElementById(\"1039\");\n",
       "  ellipsis.addEventListener(\"click\", function() {\n",
       "    var rows = document.getElementsByClassName(\"1038\");\n",
       "    for (var i = 0; i < rows.length; i++) {\n",
       "      var el = rows[i];\n",
       "      el.style.display = expanded ? \"none\" : \"table-row\";\n",
       "    }\n",
       "    ellipsis.innerHTML = expanded ? \"&hellip;)\" : \"&lsaquo;&lsaquo;&lsaquo;\";\n",
       "    expanded = !expanded;\n",
       "  });\n",
       "})();\n",
       "</script>\n"
      ],
      "text/plain": [
       "GlyphRenderer(id='1036', ...)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from bokeh.plotting import figure\n",
    "\n",
    "x_values = [1, 2, 3, 4, 5]\n",
    "y_values = [6, 7, 2, 3, 6]\n",
    "\n",
    "p = figure()\n",
    "p.circle(x=x_values, y=y_values)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When you pass in data like this, Bokeh works behind the scenes to make a `ColumnDataSource` for you. But learning to create and use the `ColumnDataSource` will enable you access more advanced capabilities, such as streaming data, sharing data between plots, and filtering data.\n",
    "\n",
    "当您像这样传递数据时，Bokeh 在幕后工作，为您生成`ColumnDataSource`。 但是，学习创建和使用`ColumnDataSource`将使您能够访问更高级的功能，如流数据、在绘图之间共享数据和过滤数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. ColumnDataSource\n",
    "The `ColumnDataSource` is the core of most Bokeh plots, providing the data that is visualized by the glyphs of the plot. With the `ColumnDataSource`, it is easy to share data between multiple plots and widgets, such as the `DataTable`. When the same `ColumnDataSource` is used to drive multiple renderers, selections of the data source are also shared. Thus it is possible to use a select tool to choose data points from one plot and have them automatically highlighted in a second plot (`Linked selection`).\n",
    "\n",
    "`Columndatasource`是大多数Bokeh图的核心，它提供由图形可视化的数据。 使用`ColumnDataSource`，可以很容易地在多个绘图和部件(如 `DataTable`)之间共享数据。 当使用相同的`ColumnDataSource`驱动多个呈现程序时，数据源的选择也是共享的。 因此，可以使用选择工具从一个图中选择数据点，并在第二个图(`链接选择`)中自动突出显示它们。\n",
    "\n",
    "At the most basic level, a ColumnDataSource is simply a mapping between column names and lists of data. The ColumnDataSource takes a data parameter which is a dict, with string column names as keys and lists (or arrays) of data values as values. If one positional argument is passed in to the ColumnDataSource initializer, it will be taken as data. Once the ColumnDataSource has been created, it can be passed into the source parameter of plotting methods which allows you to pass a column’s name as a stand in for the data values:\n",
    "\n",
    "在最基本的层次上，`ColumnDataSource`只是列名和数据列表之间的映射。`Columndatasource`接受一个数据参数，它是一个 dict，字符串列名称为键，数据值的列表(或数组)为值。 如果将一个位置参数传递给 ColumnDataSource 初始化器，则将其视为数据。 一旦 ColumnDataSource 被创建，它就可以被传递到绘图方法的源参数中，这个方法允许你传递一个列的名字作为数据值的替代:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"display: table;\"><div style=\"display: table-row;\"><div style=\"display: table-cell;\"><b title=\"bokeh.models.renderers.GlyphRenderer\">GlyphRenderer</b>(</div><div style=\"display: table-cell;\">id&nbsp;=&nbsp;'1076', <span id=\"1079\" style=\"cursor: pointer;\">&hellip;)</span></div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">data_source&nbsp;=&nbsp;ColumnDataSource(id='1040', ...),</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">glyph&nbsp;=&nbsp;Circle(id='1074', ...),</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">hover_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_event_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_property_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">level&nbsp;=&nbsp;'glyph',</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted&nbsp;=&nbsp;False,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">name&nbsp;=&nbsp;None,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">nonselection_glyph&nbsp;=&nbsp;Circle(id='1075', ...),</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">selection_glyph&nbsp;=&nbsp;None,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">subscribed_events&nbsp;=&nbsp;[],</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags&nbsp;=&nbsp;[],</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">view&nbsp;=&nbsp;CDSView(id='1077', ...),</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">visible&nbsp;=&nbsp;True,</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_range_name&nbsp;=&nbsp;'default',</div></div><div class=\"1078\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_range_name&nbsp;=&nbsp;'default')</div></div></div>\n",
       "<script>\n",
       "(function() {\n",
       "  var expanded = false;\n",
       "  var ellipsis = document.getElementById(\"1079\");\n",
       "  ellipsis.addEventListener(\"click\", function() {\n",
       "    var rows = document.getElementsByClassName(\"1078\");\n",
       "    for (var i = 0; i < rows.length; i++) {\n",
       "      var el = rows[i];\n",
       "      el.style.display = expanded ? \"none\" : \"table-row\";\n",
       "    }\n",
       "    ellipsis.innerHTML = expanded ? \"&hellip;)\" : \"&lsaquo;&lsaquo;&lsaquo;\";\n",
       "    expanded = !expanded;\n",
       "  });\n",
       "})();\n",
       "</script>\n"
      ],
      "text/plain": [
       "GlyphRenderer(id='1076', ...)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from bokeh.plotting import figure\n",
    "from bokeh.models import ColumnDataSource\n",
    "\n",
    "data = {'x_values': [1, 2, 3, 4, 5],\n",
    "        'y_values': [6, 7, 2, 3, 6]}\n",
    "\n",
    "source = ColumnDataSource(data=data)\n",
    "\n",
    "p = figure()\n",
    "p.circle(x='x_values', y='y_values', source=source)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. Pands\n",
    "The data parameter can also be a Pandas DataFrame or GroupBy object.\n",
    "\n",
    "数据参数也可以是 Pandas DataFrame 或 GroupBy 对象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If a DataFrame is used, the CDS will have columns corresponding to the columns of the DataFrame. The index of the DataFrame will be reset, so if the DataFrame has a named index column, then CDS will also have a column with this name. However, if the index name is None, then the CDS will be assigned a generic name. It will be index if it is available, and level_0 otherwise.\n",
    "\n",
    "如果使用 DataFrame，则 CDS 将具有与 DataFrame 的列相对应的列。 Dataframe 的索引将被重置，因此如果 DataFrame 有一个命名的索引列，那么 CDS 也将有一个该名称的列。 但是，如果索引名称为 None，那么将为 CDS 分配一个泛型名称。 如果可用，则为索引，否则为等级0。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.1 Pandas MultiIndex\n",
    "All MultiIndex columns and indices will be flattened before forming the ColumnsDataSource. For the index, an index of tuples will be created, and the names of the MultiIndex joined with an underscore. The column names will also be joined with an underscore. For example:\n",
    "\n",
    "在形成 ColumnsDataSource 之前，所有 MultiIndex 列和索引将被展平。 对于索引，将创建元组索引，并用下划线连接 MultiIndex 的名称。 列名也将用下划线连接起来。 例如:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "df = pd.DataFrame({('a', 'b'): {('A', 'B'): 1, ('A', 'C'): 2},\n",
    "                   ('b', 'a'): {('A', 'C'): 7, ('A', 'B'): 8},\n",
    "                   ('b', 'b'): {('A', 'D'): 9, ('A', 'B'): 10}})\n",
    "cds = ColumnDataSource(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "will result in a column named index with [(A, B), (A, C), (A, D)] and columns named a_b, b_a, and b_b. This process will fail for non-string column names, so flatten the DataFrame manually in that case.\n",
    "\n",
    "将生成一个名为 index 的列，其中包含[(a，b) ，(a，c) ，(a，d)]和名为 a b，b a 和 b 的列。 对于非字符串列名，这个过程将失败，因此在这种情况下手动压平 DataFrame。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.2 Pandas GroupBy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "group = df.groupby(('colA', 'ColB'))\n",
    "source = ColumnDataSource(group)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If a `GroupBy` object is used, the CDS will have columns corresponding to the result of calling `group.describe()`. The `describe` method generates columns for statistical measures such as `mean` and count for all the non-grouped original columns. The resulting `DataFrame` has MultiIndex columns with the original column name and the computed measure, so it will be flattened using the aforementioned scheme. For example, if a `DataFrame` has columns `'year' and 'mpg'. Then passing df.groupby('year') to a CDS will result in columns such as 'mpg_mean'\n",
    "\n",
    "如果使用 GroupBy 对象，则 CDS 将具有与调用 group.describe ()的结果相对应的列。 Describe 方法为统计度量生成列，例如所有未分组的原始列的平均值和计数。 得到的 DataFrame 具有带有原始列名和计算度量值的多索引列，因此将使用上述方案对其进行展平。 例如，如果一个 DataFrame 有“ year”和“ mpg”列。 然后将 df.groupby (‘ year’)传递给 CDS 将生成“ mpg mean”这样的列\n",
    "\n",
    "Note this capability to adapt GroupBy objects may only work with Pandas >=0.20.0.\n",
    "\n",
    "请注意，这种调整 GroupBy 对象的功能可能只适用于 Pandas 0.20.0。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
